﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Drawing2D;


namespace FustersProgressBar
{
    public partial class FustersProgressBar : ProgressBar
    {
        private string customText = "";
        private bool appendValue = false;

        public FustersProgressBar()
        {
            InitializeComponent();

            // setting the style in order to get 
            // double buffering, userpaint and redraw on resizinig 

            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
        }

        public void setCustomText(string myText, bool appendVal)
        {
            customText = myText;
            appendValue = appendVal;
        }

        // gradient top color if in gradient mode, top color otherwise 
        private Color gradientTop = Color.White;

        public Color GradientTop
        {
            get { return gradientTop; }
            set
            {
                gradientTop = value;
                this.gradientColor = myGradientColors.Custom;
                this.Invalidate();
            }
        }


        // gradient bottom color if in gradient mode	
        private Color gradientBottom = Color.Black;

        public Color GradientBottom
        {
            get { return gradientBottom; }
            set
            {
                gradientBottom = value;
                this.gradientColor = myGradientColors.Custom;
                this.Invalidate();
            }
        }


        private myGradientColors gradientColor = myGradientColors.Custom;

        [Description("Sets a predefinite gradient color. If set to custom then GradientTop and GradientBottom can be set by the user")]
        public myGradientColors GradientColor
        {
            get { return gradientColor; }
            set
            {
                gradientColor = value;
                SetGradientColors(value);
                this.Invalidate();
            }
        }

        // gradient colors enumeration 
        public enum myGradientColors
        {
            Custom, // default 
            Red,
            Blue,
            Green,
            Yellow,
            Silver
        }

        // ZProgressBar styles 
        public enum myProgressBarStyles
        {
            Simple, // default, one color 
            Gradient, // 2 colors 
            Blocks // green default blocks 
        }

        // style of the progressbar 
        private myProgressBarStyles style = myProgressBarStyles.Blocks;

        [Description("The ProgressBar style. Continuous means single color, gradient two vertically combined colors and blocks means the usual green block default ProgressBar's rendering")]
        public new myProgressBarStyles Style
        {
            get { return this.style; }
            set
            {
                this.style = value;
                if (value == myProgressBarStyles.Blocks || value == myProgressBarStyles.Simple)
                {
                    this.gradientColor = myGradientColors.Custom;
                    gradientBottom = Color.Empty;
                }
                this.Invalidate();
            }
        }

        [Browsable(true)]
        [Description("The font used to render the value")]
        public new Font Font
        {
            get { return base.Font; }
            set { base.Font = value; }
        }

        // new Value to force an invalidation 
        public new int Value
        {
            get { return base.Value; }
            set
            {
                base.Value = value;
                this.Invalidate();
            }
        }

        // shaded values 
        [Browsable(false)]
        public override RightToLeft RightToLeft
        {
            get { return base.RightToLeft; }
            set { base.RightToLeft = value; }
        }

        [Browsable(false)]
        public new int MarqueeAnimationSpeed
        {
            get { return base.MarqueeAnimationSpeed; }
            set { base.MarqueeAnimationSpeed = value; }
        }

        /// <summary> 
        /// Helper method 
        /// </summary> 
        /// <param name="gradient">The gradient to be used</param> 
        private void SetGradientColors(myGradientColors gradient)
        {
            switch (gradient)
            {
                case myGradientColors.Blue:
                    this.gradientTop = Color.AliceBlue;
                    this.gradientBottom = Color.DarkBlue;
                    break;
                case myGradientColors.Green:
                    this.gradientTop = Color.LightGreen;
                    this.gradientBottom = Color.DarkGreen;
                    break;
                case myGradientColors.Red:
                    this.gradientTop = Color.MistyRose;
                    this.gradientBottom = Color.DarkRed;
                    break;
                case myGradientColors.Silver:
                    this.gradientTop = Color.WhiteSmoke;
                    this.gradientBottom = Color.Black;
                    break;
                case myGradientColors.Yellow:
                    this.gradientTop = Color.LightYellow;
                    this.gradientBottom = Color.DarkOrange;
                    break;
            }
        } 


        protected override void OnPaint(PaintEventArgs e)
        {
            int margin = 1;
            // call to the base class OnPaint method 
            base.OnPaint(e);

            // custom painting here 
            Graphics g = e.Graphics;

            g.SmoothingMode = SmoothingMode.HighSpeed;

            int valueLen = this.Value - this.Minimum;
            valueLen *= (this.Size.Width - 2 * margin);
            valueLen /= (this.Maximum - this.Minimum);

            // foreground rectangle 
            Rectangle rect = new Rectangle(this.ClientRectangle.X + margin, this.ClientRectangle.Y + margin, valueLen, this.ClientRectangle.Height - 2 * margin);

            // background 
            // if visualstyles are applied then use the ProgressBarRenderer 
            // otherwise leave the background set by the BackColor property 
            if (Application.RenderWithVisualStyles)
            {
                ProgressBarRenderer.DrawHorizontalBar(g, this.ClientRectangle);
            }

            // foreground 
            switch (this.Style)
            {
                case myProgressBarStyles.Simple:
                    using (SolidBrush foreBrush = new SolidBrush(this.gradientTop))
                    {
                        g.FillRectangle(foreBrush, rect);
                    }
                    break;
                case myProgressBarStyles.Gradient:
                    using (LinearGradientBrush foreBrush = new LinearGradientBrush(this.ClientRectangle, gradientTop, gradientBottom, 90f))
                    {
                        foreBrush.SetBlendTriangularShape(1F);
                        g.FillRectangle(foreBrush, rect);
                    }
                    break;
                case myProgressBarStyles.Blocks:
                    if (Application.RenderWithVisualStyles)
                    {
                        ProgressBarRenderer.DrawHorizontalChunks(g, rect);
                    }
                    else
                    {
                        using (SolidBrush foreBrush = new SolidBrush(this.gradientTop))
                        {
                            g.FillRectangle(foreBrush, rect);
                        }
                    }
                    break;
            }

            string displayText = "";

            if (customText == "")
            {
                displayText = this.Value + "%";
            }
            else
            {
                displayText = customText;
                if (appendValue)
                    displayText = displayText + this.Value + "%";
            }

            using (Brush fontBrush = new SolidBrush(Color.Black))
            {
                using (StringFormat sf = new StringFormat())
                {
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Center;
                    g.DrawString(displayText, this.Font, fontBrush, this.ClientRectangle, sf);
                }
            }

            base.OnPaint(e);

        } 
    }
}
